package application

import (
	"fabric-go-sdk/sdk/sdkInfo/orgInfo"
	"fabric-go-sdk/tools"
	"fmt"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
)

func (a *Application) GetBlockchainInfo(channelId string, orgName string, userName string) (*fab.BlockchainInfoResponse, error) {
	// 检查参数
	channelId, orgName, userName, err := a.LeAndChClientParams(channelId, orgName, userName)
	if err != nil {
		return nil, fmt.Errorf("GetBlockchainInfo err:%v", err)
	}
	// 获取org实例
	org, ok := a.Channels[channelId].Orgs[orgName]
	if !ok {
		return nil, fmt.Errorf("GetBlockchainInfo err:获取org实例失败.")
	}
	// 查询
	info, err := org.GetBlockchainInfo(a.FabSDK, channelId, userName)
	if err != nil {
		return nil, fmt.Errorf("GetBlockchainInfo err: %v", err)
	}
	return info, nil
}
func (a *Application) GetConfigInfo(channelId string, orgName string, userName string) (fab.ChannelCfg, error) {
	// 检查参数
	channelId, orgName, userName, err := a.LeAndChClientParams(channelId, orgName, userName)
	if err != nil {
		return nil, fmt.Errorf("GetConfigInfo err:%v", err)
	}
	// 获取org实例
	org, ok := a.Channels[channelId].Orgs[orgName]
	if !ok {
		return nil, fmt.Errorf("GetConfigInfo err:获取组织信息实例错误.")
	}
	// 查询信息
	info, err := org.GetConfigInfo(a.FabSDK, channelId, userName)
	if err != nil {
		return nil, fmt.Errorf("GetConfigInfo err: %v", err)
	}
	return info, nil
}

// GetBlockInfo 根据区块号查询区块信息
func (a *Application) GetBlockInfo(channelId string, orgName string, userName string, n int) (*orgInfo.Block, error) {
	// 检查参数
	channelId, orgName, userName, err := a.LeAndChClientParams(channelId, orgName, userName)
	if err != nil {
		return nil, fmt.Errorf("GetBlockInfo err:%v", err)
	}
	// 获取org实例
	fmt.Println("===================", channelId, orgName, userName)
	org, ok := a.Channels[channelId].Orgs[orgName]
	if !ok {
		return nil, fmt.Errorf("GetBlockInfo err:获取组织信息实例错误.")
	}
	// 查询
	org.GetBlockInfo(a.FabSDK, channelId, userName, n, n)
	info, err := org.GetBlockInfo(a.FabSDK, channelId, userName, n, n)
	if err != nil {
		return nil, fmt.Errorf("GetBlockInfo: %v", err)
	}
	return info[0], nil
}

// GetTxInfo 根据txid查询交易
func (a *Application) GetTxInfo(channelId string, orgName string, userName string, txid string) (*orgInfo.Transaction, error) {
	// 检查参数
	channelId, orgName, userName, err := a.LeAndChClientParams(channelId, orgName, userName)
	if err != nil {
		return nil, fmt.Errorf("GetTxInfo err:%v", err)
	}
	// 获取org实例
	org, ok := a.Channels[channelId].Orgs[orgName]
	if !ok {
		return nil, fmt.Errorf("GetTxInfo err:获取组织信息实例错误.")
	}
	// 查询
	info, err := org.GetTxInfo(a.FabSDK, channelId, userName, []string{txid})
	if err != nil {
		return nil, fmt.Errorf("GetTxInfo: %v", err)
	}
	return info[0], nil
}

// GetLastFiveBlock 获取最新5个区块
func (a *Application) GetLastFiveBlock(channelId string, orgName string, userName string) ([]*orgInfo.Block, error) {
	// 检查参数
	channelId, orgName, userName, err := a.LeAndChClientParams(channelId, orgName, userName)
	if err != nil {
		return nil, fmt.Errorf("GetLastFiveBlock err:%v", err)
	}
	// 获取org实例
	org, ok := a.Channels[channelId].Orgs[orgName]
	if !ok {
		return nil, fmt.Errorf("GetLastFiveBlock err:获取组织信息实例错误.")
	}
	// 先查询出区块高度并计算开始和结束区块号
	ledgerInfo, err := org.GetBlockchainInfo(a.FabSDK, channelId, userName)
	if err != nil {
		return nil, fmt.Errorf("GetLastFiveBlock err: %s\n", err.Error())
	}
	latestBlockList := []*orgInfo.Block{}
	endNum := ledgerInfo.BCI.Height - 1 //最新的区块号--为高度-1
	startNum := endNum - 5
	if startNum <= 0 {
		startNum = 1
	}
	// 遍历查询最后五个区块
	blocks, err := org.GetBlockInfo(a.FabSDK, channelId, userName, int(startNum), int(endNum))
	if err != nil {
		return nil, fmt.Errorf("GetLastFiveBlock err:%v", err)
	}
	// 倒序区块
	for _, block := range blocks {
		latestBlockList = append(latestBlockList, block)
	}
	return latestBlockList, nil
}

// GetBlockByPage 根据页面数量限制以及页数返回对应的区块信息
func (a *Application) GetBlockByPage(channelId string, orgName string, userName string, page int, limit int) (blockList []*orgInfo.Block, blockSum int, pages int, err error) {
	// 检查参数
	channelId, orgName, userName, err = a.LeAndChClientParams(channelId, orgName, userName)
	if err != nil {
		return nil, 0, 0, fmt.Errorf("GetBlockByPage err:%v", err)
	}
	// 获取org实例
	org, ok := a.Channels[channelId].Orgs[orgName]
	if !ok {
		return nil, 0, 0, fmt.Errorf("GetBlockByPage err:获取组织信息实例错误.")
	}
	// 获取当前区块高度
	ledgerInfo, err := org.GetBlockchainInfo(a.FabSDK, channelId, userName)
	if err != nil {
		return nil, 0, 0, fmt.Errorf("GetBlockByPage err: %s\n", err.Error())
	}
	blockSum = int(ledgerInfo.BCI.Height - 1) //最新的区块号--为高度-1
	//计算出对应编号的交易
	pages, startNum, endNum := tools.CalculateStartAndEnd(blockSum, page, limit)
	// 遍历查询对应编号区块
	blockList, err = org.GetBlockInfo(a.FabSDK, channelId, userName, startNum, endNum)
	if err != nil {
		return nil, 0, 0, fmt.Errorf("GetBlockByPage err: %s\n", err.Error())
	}
	return blockList, blockSum, pages, nil
}

// GetLastestTx 获取当前最新的交易信息  --最新的五个区块中的交易
func (a *Application) GetLastestTx(channelId string, orgName string, userName string) ([]*orgInfo.Transaction, error) {
	latestBlockList, err := a.GetLastFiveBlock(channelId, orgName, userName)
	if err != nil {
		fmt.Printf("GetLastestTx error: %s\n", err)
		return nil, err
	}
	latestTxList := []*orgInfo.Transaction{}
	for _, block := range latestBlockList {
		latestTxList = append(latestTxList, block.TransactionList...)
	}
	return latestTxList, nil
}

// GetTxByPage 根据页面数量限制以及页数返回对应的交易信息
func (a *Application) GetTxByPage(channelId string, orgName string, userName string, page int, limit int) (txList []*orgInfo.Transaction, txSum int, pages int, err error) {
	// 检查参数
	channelId, orgName, userName, err = a.LeAndChClientParams(channelId, orgName, userName)
	if err != nil {
		return nil, 0, 0, fmt.Errorf("GetBlockByPage err:%v", err)
	}
	// 获取org实例
	org, ok := a.Channels[channelId].Orgs[orgName]
	if !ok {
		return nil, 0, 0, fmt.Errorf("GetBlockByPage err:获取组织信息实例错误.")
	}
	// 获取当前交易总数以及交易哈希列表
	txHashlist, txSum, err := a.GetTxHashList(channelId, orgName, userName)
	if err != nil {
		return nil, 0, 0, fmt.Errorf("GetTxByPage err:%v", err)
	}

	//计算出对应编号的交易
	pages, startNum, endNum := tools.CalculateStartAndEnd(txSum, page, limit)
	// 查询交易
	txList, err = org.GetTxInfo(a.FabSDK, channelId, userName, txHashlist[startNum-1:endNum])
	if err != nil {
		return nil, 0, 0, fmt.Errorf("GetTxByPage err:%v", err)
	}
	return txList, txSum, pages, nil
}

//GetTxHashList 获取所有交易列表以及交易总数
func (a *Application) GetTxHashList(channelId string, orgName string, userName string) (txHashList []string, sum int, err error) {
	// 检查参数
	channelId, orgName, userName, err = a.LeAndChClientParams(channelId, orgName, userName)
	if err != nil {
		return nil, 0, fmt.Errorf("GetTxHashList err:%v", err)
	}
	// 获取org实例
	org, ok := a.Channels[channelId].Orgs[orgName]
	if !ok {
		return nil, 0, fmt.Errorf("GetTxHashList err:获取组织信息实例错误.")
	}
	// 获取leClient客户端
	leClient, err := org.CreatLedgerClient(a.FabSDK, channelId, userName)
	if err != nil {
		return nil, 0, fmt.Errorf("GetTxHashList err:%v", err)
	}
	// 查询当前区块高度
	ledgerInfo, err := leClient.QueryInfo()
	if err != nil {
		fmt.Printf("GetTxHashList err: %s\n", err)
		return nil, 0, err
	}
	BlockNum := int(ledgerInfo.BCI.Height - 1) //最新的区块号--为高度-1
	//遍历所有区块
	for i := 1; i <= BlockNum; i++ {
		Block, err := leClient.QueryBlock(uint64(i))
		if err != nil {
			fmt.Printf("QueryBlock return error: %s", err)
			return nil, 0, err
		}
		sum += len(Block.Data.Data) //记录交易总数
		for i := range Block.Data.Data {
			rawEnvelope, err := orgInfo.GetEnvelopeFromBlock(Block.Data.Data[i])
			if err != nil {
				fmt.Println("GetEnvelopeFromBlock err:", err)
				return nil, 0, err
			}
			payload, err := orgInfo.GetPayloadFromEnvelope(rawEnvelope)
			if err != nil {
				fmt.Println("GetPayloadFromEnvelope err:", err)
				return nil, 0, err
			}
			channelHeader, err := orgInfo.GetChannelHeaderFromPayload(payload)
			if err != nil {
				fmt.Println("GetChannelHeaderFromPayload err:", err)
				return nil, 0, err
			}
			txHashList = append(txHashList, channelHeader.TxId)
		}
	}
	return txHashList, sum, nil
}
